from django.shortcuts import render, HttpResponse
from app.models import Case2
import jieba
#基于TF-IDF 文本相似性实战
# coding=utf-8
import jieba.analyse,os
from sklearn.feature_extraction.text import CountVectorizer
import numpy as np
import pandas as pd
from scipy.linalg import norm
from tqdm import tqdm
#基于Word2Vec 文本相似性实战
# pip install annoy -i https://pypi.tuna.tsinghua.edu.cn/simple --trusted-host pypi.tuna.tsinghua.edu.cn
# pip install gensim==4.2.0 -i https://pypi.tuna.tsinghua.edu.cn/simple --trusted-host pypi.tuna.tsinghua.edu.cn
# （嘎嘎快）pip install matplotlib -i https://mirrors.aliyun.com/pypi/simple/
#pip install openpyxl -i https://mirrors.aliyun.com/pypi/simple/
from sklearn.metrics import f1_score
from datetime import datetime
import time
from collections import Counter
import re
from annoy import AnnoyIndex
import os
import gensim
from gensim.models import KeyedVectors
from gensim.scripts.glove2word2vec import glove2word2vec
from gensim.models import Word2Vec
from gensim.models.word2vec import LineSentence
print("gensim.__version__",gensim.__version__) # 4.2.0
import matplotlib.pyplot as plt
plt.rcParams["font.sans-serif"] = ['Simhei']
plt.rcParams["axes.unicode_minus"] = False

#句子预处理
def pretreatment(text):#数据预处理
    # 1、分词处理
    text = jieba.cut(text.strip())
    # 2、去除停用词
    # 创建一个停用词列表
    stopwords = [line.strip() for line in
                 open('D:\pythonCode\Word2VecMedical\\app\data\stopwords.txt', encoding='UTF-8').readlines()]
    sentence = ''
    # 去停用词
    for word in text:
        if word not in stopwords:
            if word != '\t':
                sentence += word
                sentence += " "
    return sentence

#TF词频统计算法
def tf_similarity(s1, s2):
    cv = CountVectorizer(tokenizer=lambda s: s.split())
    corpus = [s1, s2]
    vectors = cv.fit_transform(corpus).toarray()
    # print(vectors)
    # 计算TF系数
    return np.dot(vectors[0], vectors[1]) / (norm(vectors[0]) * norm(vectors[1]))


#搜索功能（获取匹配列表）
def do_search_(request):
    if request.method=="POST":
        #1、获取搜索页面提交的描述字符
        description=request.POST.get("description")
        top_k = request.POST.get("num")
        #nums = re.findall("\d", description)
        #top_k=''
        #for n in nums:
        #    top_k += n
        #print(type(top_k))
        if(top_k!=''):
            top_k=int(top_k)
            if(top_k>100):
                top_k=10
        else:
            top_k=int('10')
        print("-----------------------------------------------------------------------")
        most_similar_case_names = search_by_words(description,top_k)#调用word2vec算法
        #2、获取数据库中的全部信息
        data_list = Case2.objects.all()
        #3、创建数据字典和数据列表（盛装字典数据）
        data_dict={}
        Data=[]
        '''
        #5、计算相似度TF词频统计算法
        for data in data_list:
            name = data.case_name
            introduction = data.case_introduction
            symbols = data.case_detail_symptoms#获取数据库中的病症描述
            symbols = pretreatment(symbols)#--------对数据库中的病症描述进行数据处理
            value = tf_similarity(sentence, symbols)#使用tf算法计算用户描述和数据库中的病症描述的词频相似度
            if(value>=0.1):#设置相似度阈值为0.5
                data_dict["value"] = value
                data_dict["name"]=name
                data_dict["introduction"]=introduction
                #print(data_dict[value],data_dict[name],data_dict[introduction])
                Data.append(data_dict)# 将键值对以元组的形式存放（方便后续使用sort函数进行排序），最后保存在一个列表中
                data_dict={}#data_list是河水，data_dict是瓢，Data是桶，每次用字典data_dict从data_list中取出一瓢倒入桶中，水瓢都是清空后的状态再继续舀水的。
        for d in Data:
            print(d)
        print("-----------------------------------------------------------------------")
        #6、根据列表元素元组中的【value】键值进行排序//参考：https://blog.csdn.net/qq_43030934/article/details/130362853
        Data.sort(key=lambda data:data['value'],reverse=True);#根据列表第1个元素排序（默认为根据第一个元素进行排序）# reverse=True--降序排序
        for d in Data:
            print(d)
        '''
        index=0
        #4、在数据库中搜索与算法结果名字相同的病例
        for data in data_list:#遍历数据库列表
            name = data.case_name
            introduction = data.case_introduction
            for similar_name in most_similar_case_names:
                if(name == similar_name):
                    data_dict["name"] = name
                    data_dict["introduction"] = introduction
                    #拒绝加入重复病例数据
                    if data_dict not in Data:
                        index += 1
                        data_dict["index"] = index
                        Data.append(data_dict)
                    data_dict = {}
        #for d in Data:
        #    print(d)
        print("-----------------------------------------------------------------------")
        return render(request, 'get_list_.html', {"datas": Data})
    return render(request,'do_search_.html')

#深度学习算法Word2Vec
def search_by_words(key_input,top_k):#key_input用户输入的病症描述
    #data=pd.read_excel("case_information_1800_csv.xlsx")
    #query_list=data['case_name'].values.tolist()#将Excel表中的case_name列装入列表query_list
    #answer_list=data['case_detail_symptoms'].values.tolist()#将Excel表中的case_detail_symptoms列装入列表answer_list
    query_list=[]
    answer_list=[]
    data_list = Case2.objects.all()# 获取数据库中的全部信息
    for case in data_list:
        query_list.append(case.case_name)
        answer_list.append(case.case_detail_symptoms)

#患者自觉龟头或阴茎部疼痛、灼热及a瘙痒感，与衣裤磨擦后加重。由于阴茎头坠胀及衣裤摩擦，有时活动不便
    model_vec = gensim.models.Word2Vec.load('D:\pythonCode\Word2VecMedical\\app\word2vec.model')
    dic = model_vec.wv.index_to_key
    print(len(dic))
    # 为所有的句子建立一个向量库进行索引：
    f=64
    t = AnnoyIndex(f, 'angular')  # Length of item vector that will be indexed
    for index_i,line in enumerate(tqdm(answer_list)):
        # print(line)
        line = "".join(re.findall('[\u4e00-\u9fa5]', str(line)))
        line = jieba.cut(line, cut_all=False)
        temp_vec=np.zeros((1,64))
        for word in line:
            try:
                vec = model_vec.wv[word]  # 从词库里面取出这些词对应的向量
            except KeyError:  # 当在词向量模型中没有这个单词的向量的时候可以设置错误跳过 然后把这个单词的向量设置为全0
                vec = np.zeros((1, 64))
            temp_vec = temp_vec + vec
        t.add_item(index_i, temp_vec[0])

    # 把最新输入的句子变成向量加到 生成新的模型 检索
    # key_input=input("请输入您的症状：")# 脱出，伴有肛门外分泌物、瘙痒、肛门外硬结、皮肤溃疡等相关症状
    key_input= "".join(re.findall('[\u4e00-\u9fa5]', str(key_input)))
    key_input=jieba.cut(key_input, cut_all=False)
    input_vec=np.zeros((1,64))
    idx_input=len(answer_list)+1
    print('idx_input',idx_input)
    for word in key_input:
        #print(word)
        try:
            vec = model_vec.wv[word]  #从词库里面取出这些词对应的向量
            # print(word)
        except KeyError:        #当在词向量模型中没有这个单词的向量的时候可以设置错误跳过 然后把这个单词的向量设置为全0
            vec=np.zeros((1,64))
        input_vec=input_vec+vec
    t.add_item(idx_input, input_vec[0])

    t.build(100)
    t.save('embeedding.ann')
    u = AnnoyIndex(f, 'angular')
    u.load('embeedding.ann')
    temp=u.get_nns_by_item(idx_input,100)#
    print(temp)
    res=[]
    for i in temp[1:top_k+1]:
        res.append(str(query_list[i]))#返回与描述最相似与的病例名字
    return res


#获取详情页面信息
def get_details_(request,uname):
    data_details = Case2.objects.all().filter(case_name=uname).first()
    return render(request,'get_details_.html',{"data_details":data_details})

